package common.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;


/**
 * Ingresa un nombre de archivo y el numero de numeros que tiene cada file de este.
 * Al ejecutar queda una matriz de numeros flotantes, con la misma estructura que el archivo 
 * de enntrada, pero los valores de esta matriz estan normalizados.
 * 
 * @author Martin
 *
 */
public class FromFileToFloatArray {
	
	private static final Logger  logger  = Logger.getLogger(FromFileToFloatArray.class);


	public static Float maximo=new Float(0.0);
	public static Float minimo=new Float(0.0);

	//Voy a poner como limite de normalizacion de valores a 
	//max -> 146; min -> -100; paso a positivos sumandoles 100 a todos
	//(los que queden negativos los paso al minimo 0, lo mismo los que se pasan para arriba 246)
	public static Float maxNorm=new Float(246.0);
	public static Float minNorm=new Float(0.0);
	public static Float deltaNorm=new Float(100.0);
	
	private List< List<Float> > matriz;
	
//	public FromFileToFloatArray(String nombreArchivo, int numPorLinea) {
//		matriz=new ArrayList<List<Float> >();
//		execute(nombreArchivo,numPorLinea);
//	}

//	public FromFileToFloatArray(File archivo, int numPorLinea) {
//		matriz=new ArrayList<List<Float> >();
//		execute(archivo,numPorLinea);
//	}

	public FromFileToFloatArray() {
		matriz=new ArrayList<List<Float> >();
	}	
	
	private boolean isNumeric(String valor){
		try {
			Float.parseFloat(valor);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

//	private void execute(String nombreArchivo, int numPorLinea) {
//		
//		FileReader fr;
//		try {
////			nombreArchivo="per-01.txt";
//			//si pongo directamente un nombre, lo toma desde el raiz del proyecto
//			fr = new FileReader(nombreArchivo);
//			BufferedReader bf = new BufferedReader(fr);
	
	
	public static void main(String[] args) {
		String sCadena="-hola-chau-dia";
	
		String[] val=getValores(sCadena);
		
		for (int i=0;i<val.length;i++){
			System.out.println(val[i]);
		}
		
	}
	
	
/*	
	private void execute(File archivo, int numPorLinea) {
		logger.info("procesando arch:" + archivo.getAbsolutePath());
		FileReader fr;
		try {
//			nombreArchivo="per-01.txt";
			//si pongo directamente un nombre, lo toma desde el raiz del proyecto
			fr = new FileReader(archivo);
			BufferedReader bf = new BufferedReader(fr);
		
			String sCadena=null;
			
			List<Float> listLinea =null;
			
			while ((sCadena = bf.readLine())!=null) {

				if ( isNumeric(sCadena.substring(0,1)) ){
				
					String[] valores=sCadena.split(" ");
	
					listLinea = new ArrayList<Float>();
	
					for (String valor:valores){
						
						if ( valor!=null && !valor.equals("") ){
							
							if ( !isNumeric(valor) ){
								//puede suceder si se me junta el menos de un numero siguiente con el actual, quedan 2 numeros
								String[] subValores=sCadena.split("-");
								
								//si es mayor a 1, entonces voy separando los valores
								if (subValores.length>1){

									String[] valoresStrings = getValores(valor);
									
									for (String floatVal:valoresStrings){
										
										if ( floatVal!=null && !floatVal.equals("") && isNumeric(floatVal) ){
											Float val=Float.parseFloat(floatVal);
											listLinea.add(normaliza(val));
											
											//obtener maximos y minimos
											if (val>maximo)
												maximo=val;
											if (val<minimo)
												minimo=val;
											
											System.out.println("Original: "+val +", nomrmalizado: " +normaliza(val) );
									//		System.out.println(valor);
										
										}

									}
								}
							}
							else{
							
								Float val=Float.parseFloat(valor);
								listLinea.add(normaliza(val));
								
								//obtener maximos y minimos
								if (val>maximo)
									maximo=val;
								if (val<minimo)
									minimo=val;
								
								System.out.println("Original: "+val +", nomrmalizado: " +normaliza(val) );
						//		System.out.println(valor);
								}
							}
					}
					matriz.add(listLinea);
				}
			}

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
			
		 System.out.println("fin proceso.");
	}
*/
	
	public void executeWithOutNormalize(File archivo) {
		logger.info("procesando arch:" + archivo.getAbsolutePath());
		FileReader fr;
		try {
//			nombreArchivo="per-01.txt";
			//si pongo directamente un nombre, lo toma desde el raiz del proyecto
			fr = new FileReader(archivo);
			BufferedReader bf = new BufferedReader(fr);
		
			String sCadena=null;
			
			List<Float> listLinea =null;
			
			while ((sCadena = bf.readLine())!=null) {

				if ( isNumeric(sCadena.substring(0,1)) ){
				
					String[] valores=sCadena.split(" ");
	
					listLinea = new ArrayList<Float>();
	
					for (String valor:valores){
						
						if ( valor!=null && !valor.equals("") ){
							
							if ( !isNumeric(valor) ){
								//puede suceder si se me junta el menos de un numero siguiente con el actual, quedan 2 numeros
								String[] subValores=sCadena.split("-");
								
								//si es mayor a 1, entonces voy separando los valores
								if (subValores.length>1){

									String[] valoresStrings = getValores(valor);
									
									for (String floatVal:valoresStrings){
										
										if ( floatVal!=null && !floatVal.equals("") && isNumeric(floatVal) ){
											Float val=Float.parseFloat(floatVal);
											listLinea.add(val);
											
											//obtener maximos y minimos
											if (val>maximo)
												maximo=val;
											if (val<minimo)
												minimo=val;
											
									//		System.out.println("Original: "+val );
																			
										}

									}
								}
							}
							else{
							
								Float val=Float.parseFloat(valor);
								listLinea.add(val);
								
								//obtener maximos y minimos
								if (val>maximo)
									maximo=val;
								if (val<minimo)
									minimo=val;
								
						//		System.out.println("Original: "+val  );
						
								}
							}
					}
					matriz.add(listLinea);
				}
			}

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
			
		 logger.info("fin proceso.");
	}

	
	/**
	 * Me llega varios numeros unidos por menos, y los tengo que separar
	 * ejemplo "3.253-2.365 -> 3.253 -2.365"
	 * @param valor
	 * @return
	 */
	private static String[] getValores(String cadena) {
		
		String resultado="";
		
		String[] valores = cadena.split("-");
		
		if (!valores[0].equals("")){
			resultado+=valores[0]+";";
		}
		
		for (int i = 1; i < valores.length; i++) {
			resultado+="-"+valores[i]+";";
		}

		return resultado.split(";");
	}

	private Float normaliza(Float valor){
		valor+=deltaNorm;
		if (valor<minNorm)
			valor=minNorm;
		if (valor>maxNorm)
			valor=maxNorm;

		return valor/maxNorm;
		
	}
	
	/**
	 * Le paso el maximo y minimo y me setea el rango
	 * @param max
	 * @param min
	 */
	public static void setMaxMinNormalizedValues(Float max,Float min){
		
		deltaNorm=-min;
		maxNorm=deltaNorm+max;
		minNorm=new Float(0.0);
		

	}
	
	public void mostrarValores() {
		for (List<Float> linea:matriz){
		
			for (Float valor:linea){
				System.out.print(valor+"  ");
			}
			System.out.println("nueava linea");
		}
		
	}


	public List<List<Float>> getMatriz() {
		return matriz;
	}


	public void setMatriz(List<List<Float>> matriz) {
		this.matriz = matriz;
	}
	
	/**
	 * Toma la matriz y normaliza cada fila de esta a un solo valor
	 * @return devuelve una lista de valores reppresentando cada valor a una fila de la matriz
	 */
/*	public List<Float> normaliceByLines(int numByLine){
		List<Float> lista= new ArrayList<Float>();

		for (List<Float> linea:matriz){
			Float sumVal=new Float(0.0);
			for (Float valor:linea){
				sumVal+=valor;
			}
			
			lista.add(sumVal/numByLine);
		}

		return lista;
		
	}
*/
	
	/**
	 * Toma la matriz y me devuelve una lista con los valores
	 * que estan en la columna que paso por parametro
	 *
	 * @return devuelve una lista de valores reppresentando cada valor a una fila de la matriz
	 */
/*	public List<Float> getValuesByColumn(int columnNumber){
		List<Float> lista= new ArrayList<Float>();

		for (List<Float> linea:matriz){
			
			lista.add(linea.get(columnNumber));
		
		}

		return lista;
		
	}
*/
	
	
	
	/**
	 * Toma la matriz y me devuelve una lista con los valores
	 * que estan en la columna que paso por parametro normalizados
	 *
	 * @return devuelve una lista de valores reppresentando cada valor a una fila de la matriz
	 */
	public List<Float> getValuesByColumnAndNormalice(int columnNumber){
		
		List<Float> lista= new ArrayList<Float>();

		for (List<Float> linea:matriz){
			
			lista.add(normaliza(linea.get(columnNumber)));
		
		}

		return lista;
		
	}
	
//////////////////////////////////////////////////////////////////////
/////////obtiene maximos y minimos por coeficiente////////////////////
	
	public static Float coefmaximo=new Float(0.0);
	public static Float coefminimo=new Float(0.0);

	public static Float secondMax=new Float(0.0);
	public static Float secondMin=new Float(0.0);

	public static void resetMaxAndMin(){
		coefmaximo=new Float(0.0);
		coefminimo=new Float(200.0);
		
		secondMax=new Float(0.0);
		secondMin=new Float(200.0);
	}
	
	public static void main2(String[] args) {
		String pathArchivos="D:/WAVS_TO_COEF/";
		
		GetAllFilesOfDir g=new GetAllFilesOfDir();
		List<File> lista=new ArrayList<File>();
		lista.addAll(g.getListNameOfFilesInDir(pathArchivos+"mfccTextCoef/asegura"));
		
		FromFileToFloatArray fileToFloatArray=new FromFileToFloatArray();
		
		//lleno las matrices con los valores normalizados
		for (File file: lista){
			fileToFloatArray.getMaxAndMinByCoef(file,1);
		}
	
	}
		
	
	public void getMaxAndMinByCoef(File archivo, int coef) {
//		System.out.println("procesando arch:" + archivo.getAbsolutePath()+ ", para el coef "+coef);
		FileReader fr;
		try {

			fr = new FileReader(archivo);
			BufferedReader bf = new BufferedReader(fr);
		
			String sCadena=null;
			
			while ((sCadena = bf.readLine())!=null) {

				if ( isNumeric(sCadena.substring(0,1)) ){
				
					String[] valores=sCadena.split(" ");
	
					int coefNumber=1;
					
					for (String valor:valores){
						
						if ( valor!=null && !valor.equals("") && isNumeric(valor) ){
							
							Float val=Float.parseFloat(valor);
								
							//obtener maximos y minimos
							if (coefNumber == coef){
								if (val>coefmaximo)
									coefmaximo=val;
								if (val<coefminimo)
									coefminimo=val;
								
								//actualizo segundos maximos y minimos
								if (val>secondMax && val<coefmaximo)
									secondMax=val;
								if (val<secondMin && val > coefminimo)
									secondMin=val;
								
							}
							coefNumber++;
						}
					}

				}
			}

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
			
//		 System.out.println("fin proceso.");
	}
	
	
	
}
